home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / file-tra / fsp-2.7 / fsp-2 / fsp / bsd_src / operator.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-07  |  7.7 KB  |  260 lines

  1. /*-
  2.  * Copyright (c) 1990 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Cimarron D. Taylor of the University of California, Berkeley.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #include "tweak.h"
  38. #ifndef VMS
  39. #include <sys/types.h>
  40. #include <sys/stat.h>
  41. #else
  42. #include "types.h"
  43. #include "stat.h"
  44. #endif
  45. #include <stdio.h>
  46. #include "find.h"
  47.  
  48. /*
  49.  * yanknode --
  50.  *    destructively removes the top from the plan
  51.  */
  52. static PLAN *yanknode PROTO1(PLAN **, planp)    
  53. {
  54.   PLAN *node;        /* top node removed from the plan */
  55.   
  56.   if ((node = (*planp)) == NULL) return(NULL);
  57.   (*planp) = (*planp)->next;
  58.   node->next = NULL;
  59.   return(node);
  60. }
  61.  
  62. /*
  63.  * yankexpr --
  64.  *    Removes one expression from the plan.  This is used mainly by
  65.  *    paren_squish.  In comments below, an expression is either a
  66.  *    simple node or a N_EXPR node containing a list of simple nodes.
  67.  */
  68. static PLAN *yankexpr PROTO1(PLAN **, planp)    
  69. {
  70.   register PLAN *next;    /* temp node holding subexpression results */
  71.   PLAN *node;           /* pointer to returned node or expression */
  72.   PLAN *tail;        /* pointer to tail of subplan */
  73.   PLAN *subplan;    /* pointer to head of ( ) expression */
  74.   
  75.   /* first pull the top node from the plan */
  76.   if ((node = yanknode(planp)) == NULL) return(NULL);
  77.   
  78.   /*
  79.    * If the node is an '(' then we recursively slurp up expressions
  80.    * until we find its associated ')'.  If it's a closing paren we
  81.    * just return it and unwind our recursion; all other nodes are
  82.    * complete expressions, so just return them.
  83.    */
  84.   if (node->type == N_OPENPAREN)
  85.     for (tail = subplan = NULL;;) {
  86.       if ((next = yankexpr(planp)) == NULL)
  87.     fprintf(stderr,"(: missing closing ')'");
  88.       /*
  89.        * If we find a closing ')' we store the collected
  90.        * subplan in our '(' node and convert the node to
  91.        * a N_EXPR.  The ')' we found is ignored.  Otherwise,
  92.        * we just continue to add whatever we get to our
  93.        * subplan.
  94.        */
  95.       if (next->type == N_CLOSEPAREN) {
  96.     if (subplan == NULL) {
  97.       fprintf(stderr,"(): empty inner expression");
  98.       exit(1);
  99.     }
  100.     node->p_data[0] = subplan;
  101.     node->type = N_EXPR;
  102.     node->eval = find_expr;
  103.     break;
  104.       } else {
  105.     if (subplan == NULL) tail = subplan = next;
  106.     else {
  107.       tail->next = next;
  108.       tail = next;
  109.     }
  110.     tail->next = NULL;
  111.       }
  112.     }
  113.   return(node);
  114. }
  115.  
  116. /*
  117.  * paren_squish --
  118.  *    replaces "parentheisized" plans in our search plan with "expr" nodes.
  119.  */
  120. PLAN *paren_squish PROTO1(PLAN *, plan)
  121. {
  122.   register PLAN *expr;    /* pointer to next expression */
  123.   register PLAN *tail;    /* pointer to tail of result plan */
  124.   PLAN *result;        /* pointer to head of result plan */
  125.   
  126.   result = tail = NULL;
  127.   
  128.   /*
  129.    * the basic idea is to have yankexpr do all our work and just
  130.    * collect it's results together.
  131.    */
  132.   while ((expr = yankexpr(&plan)) != NULL) {
  133.     /*
  134.      * if we find an unclaimed ')' it means there is a missing
  135.      * '(' someplace.
  136.      */
  137.     if (expr->type == N_CLOSEPAREN) {
  138.       fprintf(stderr,"): no beginning '('");
  139.       exit(1);
  140.     }
  141.     
  142.     /* add the expression to our result plan */
  143.     if (result == NULL) tail = result = expr;
  144.     else {
  145.       tail->next = expr;
  146.       tail = expr;
  147.     }
  148.     tail->next = NULL;
  149.   }
  150.   return(result);
  151. }
  152.  
  153. /*
  154.  * not_squish --
  155.  *    compresses "!" expressions in our search plan.
  156.  */
  157. PLAN *not_squish PROTO1(PLAN *, plan)
  158. {
  159.   register PLAN *next;    /* next node being processed */
  160.   register PLAN *node;    /* temporary node used in N_NOT processing */
  161.   register PLAN *tail;    /* pointer to tail of result plan */
  162.   PLAN *result;        /* pointer to head of result plan */
  163.   
  164.   tail = result = next = NULL;
  165.   
  166.   while ((next = yanknode(&plan)) != NULL) {
  167.     /*
  168.      * if we encounter a ( expression ) then look for nots in
  169.      * the expr subplan.
  170.      */
  171.     if (next->type == N_EXPR) next->p_data[0] = not_squish(next->p_data[0]);
  172.     
  173.     /*
  174.      * if we encounter a not, then snag the next node and place
  175.      * it in the not's subplan.  As an optimization we compress
  176.      * several not's to zero or one not.
  177.      */
  178.     if (next->type == N_NOT) {
  179.       int notlevel = 1;
  180.       
  181.       node = yanknode(&plan);
  182.       while (node->type == N_NOT) {
  183.     ++notlevel;
  184.     node = yanknode(&plan);
  185.       }
  186.       if (node == NULL) {
  187.     fprintf(stderr,"!: no following expression");
  188.     exit(1);
  189.       }
  190.       if (node->type == N_OR) {
  191.     fprintf(stderr,"!: nothing between ! and -o");
  192.     exit(1);
  193.       }
  194.       if (notlevel % 2 != 1) next = node;
  195.       else next->p_data[0] = node;
  196.     }
  197.     
  198.     /* add the node to our result plan */
  199.     if (result == NULL) tail = result = next;
  200.     else {
  201.       tail->next = next;
  202.       tail = next;
  203.     }
  204.     tail->next = NULL;
  205.   }
  206.   return(result);
  207. }
  208.  
  209. /*
  210.  * or_squish --
  211.  *    compresses -o expressions in our search plan.
  212.  */
  213. PLAN *or_squish PROTO1(PLAN *, plan)
  214. {
  215.   register PLAN *next;    /* next node being processed */
  216.   register PLAN *tail;    /* pointer to tail of result plan */
  217.   PLAN *result;        /* pointer to head of result plan */
  218.   
  219.   tail = result = next = NULL;
  220.   
  221.   while ((next = yanknode(&plan)) != NULL) {
  222.     /*
  223.      * if we encounter a ( expression ) then look for or's in
  224.      * the expr subplan.
  225.      */
  226.     if (next->type == N_EXPR) next->p_data[0] = or_squish(next->p_data[0]);
  227.     
  228.     /* if we encounter a not then look for not's in the subplan */
  229.     if (next->type == N_NOT) next->p_data[0] = or_squish(next->p_data[0]);
  230.     
  231.     /*
  232.      * if we encounter an or, then place our collected plan in the
  233.      * or's first subplan and then recursively collect the
  234.      * remaining stuff into the second subplan and return the or.
  235.      */
  236.     if (next->type == N_OR) {
  237.       if (result == NULL) {
  238.     fprintf(stderr,"-o: no expression before -o");
  239.     exit(1);
  240.       }
  241.       next->p_data[0] = result;
  242.       next->p_data[1] = or_squish(plan);
  243.       if (next->p_data[1] == NULL) {
  244.     fprintf(stderr,"-o: no expression after -o");
  245.     exit(1);
  246.       }
  247.       return(next);
  248.     }
  249.     
  250.     /* add the node to our result plan */
  251.     if (result == NULL) tail = result = next;
  252.     else {
  253.       tail->next = next;
  254.       tail = next;
  255.     }
  256.     tail->next = NULL;
  257.   }
  258.   return(result);
  259. }
  260.